package org.company.earth.concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockStorage {
	
	private final Integer MAX = 10;
	private Integer count = MAX;
	List<Object> storage = new ArrayList<Object>(count);
	private Lock lock = new ReentrantLock();
	private Condition full = lock.newCondition();
	private Condition empty = lock.newCondition();
	private static LockStorage instance = null;
	
	private LockStorage() {
		
	}
	
	public static LockStorage getInstance() {
		if(instance == null)
			instance = new LockStorage();
		return instance;
	}
	
	public void put(Object o) throws InterruptedException {
		lock.lock();
		try{
		    try{
    			while(storage.size() == MAX)
    				full.await();
		    }catch(InterruptedException e) {
		        full.signal();
		        throw e;
		    }
			storage.add(o);
			System.out.println("add" + o);
		}finally {
			lock.unlock();
		}
	}
	 
	public void take() throws InterruptedException {
		lock.lock();
		try{
			while(storage.size() == 0)
				empty.await();
			Object o = storage.remove(storage.size()-1);
			System.out.println("take" + o);
		}finally {
			lock.unlock();
		}
	}
	
	public static void main(String[] args) {
		new Thread() {
			public void run() {
				LockStorage storage = LockStorage.getInstance();
				for(int i = 0 ;i<20; i++) {
					try {
						storage.put(new Integer(i));
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}.start();
		
		new Thread() {
			public void run() {
				LockStorage storage = LockStorage.getInstance();
				for(int i = 0 ;i<20; i++) {
					try {
						storage.take();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}.start();
		
		try {
            Thread.sleep(1000*60);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
	}
}
